package com.mrjy.wechat.util;


import com.mrjy.common.util.WechatSendTemplate;
import com.mrjy.wechat.conts.WxConsts;
import com.mrjy.wechat.dto.TemplateMessage;
import com.mrjy.wechat.process.AccessToken;
import net.sf.json.JSONObject;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 微信配置信息及api URL的获取
 *
 * @author csshui
 *
 */
public class WeChatUtil {
	
	/**
	 * 对url进行转码
	 * @param str
	 * @return
	 */
	public static String urlEnodeUTF8(String str){
        String result = str;
        try {
            result = URLEncoder.encode(str,"UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

	/**
	 * https请求
	 * @param requestUrl 请求url
	 * @param requestMethod 请求方法
	 * @param outputStr  post请求的参数
	 * @return
	 */
	public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		try {
			TrustManager[] tm = { new JEEWeChatX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			
			URL url = new URL(requestUrl);
			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
			conn.setSSLSocketFactory(ssf);

			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod(requestMethod);
			if (null != outputStr) {
				OutputStream outputStream = conn.getOutputStream();
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}
			InputStream inputStream = conn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String str = null;
			StringBuffer buffer = new StringBuffer();
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
			conn.disconnect();
			jsonObject = JSONObject.fromObject(buffer.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jsonObject;
	}
	
	 /** 
     * 验证签名 
     * @param signature 
     * @param timestamp 
     * @param nonce 
     * @return 
     */  
    public static boolean checkSignature(String signature, String timestamp, String nonce) {  
        String[] arr = new String[] { WxConsts.SIGN_TOKEN, timestamp, nonce };  
        // 将 token、timestamp、nonce 三个参数进行字典序排序   
        Arrays.sort(arr);  
        StringBuilder content = new StringBuilder();  
        for (int i = 0; i < arr.length; i++) {  
            content.append(arr[i]);  
        }  
        MessageDigest md = null;  
        String tmpStr = null;  

        try {  
            md = MessageDigest.getInstance("SHA-1");  
            // 将三个参数字符串拼接成一个字符串进行 sha1 加密   
            byte[] digest = md.digest(content.toString().getBytes());  
            tmpStr = byteToStr(digest);  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
        }  

        content = null;  
        // 将 sha1 加密后的字符串可与 signature 对比，标识该请求来源于微信   
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;  
    } 
    
    public static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
    
    public static String byteToStr(byte[] byteArray) {
		String rst = "";
		for (int i = 0; i < byteArray.length; i++) {
			rst += byteToHex(byteArray[i]);
		}
		return rst;
	}
	
	public static String byteToHex(byte b) {
		char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		char[] tempArr = new char[2];
		tempArr[0] = Digit[(b >>> 4) & 0X0F];
		tempArr[1] = Digit[b & 0X0F];
		String s = new String(tempArr);
		return s;
	}
	/**
	 * 发起http请求并获取结果
	 * 
	 * @param requestUrl 请求地址
	 * @param requestMethod 请求方式（GET、POST）
	 * @param paramStr post请求的参数
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static JSONObject httpRequest(String requestUrl, String requestMethod, String paramStr) {
		JSONObject jsonObject = null;
		StringBuilder builder = new StringBuilder();
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
//			TrustManager[] tm = { new MyX509TrustManager() };
//			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
//			sslContext.init(null, tm, new java.security.SecureRandom());
//			// 从上述SSLContext对象中得到SSLSocketFactory对象
//			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
//			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);

			if (WxConsts.HTTP_GET.equalsIgnoreCase(requestMethod))
				httpUrlConn.connect();

			// 当有数据需要提交时
			if (null != paramStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 编码格式，防止中文乱码
				outputStream.write(paramStr.getBytes("UTF-8"));
				outputStream.close();
			}

			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				builder.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			// 释放资源
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();
			jsonObject = JSONObject.fromObject(builder.toString());
		} catch (ConnectException ce) {
			ce.printStackTrace();
			System.out.println("网络链接失败！");
		}catch (UnknownHostException uhe) {
			uhe.printStackTrace();
			System.out.println("微信API无法访问....！");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jsonObject;
	}
	
	public static Object sendWechatTemplateMessage(TemplateMessage message){
		Map<String, Object> map = new HashMap<String, Object>();
		if(null == message){
			map.put("err_code", 40001);
			map.put("err_msg", "传入message为null");
			return map;
		}
		
		WechatSendTemplate wst = WechatSendTemplate.SEND_TEMPLATE_01;
		switch (message.getSendType()) {
		case "1":
			wst = WechatSendTemplate.SEND_TEMPLATE_01;
			break;
		case "2":
			wst = WechatSendTemplate.SEND_TEMPLATE_02;
			break;
		case "3":
			wst = WechatSendTemplate.SEND_TEMPLATE_03;
			break;
		case "4":
			wst = WechatSendTemplate.SEND_TEMPLATE_04;
			break;
		case "5":
			wst = WechatSendTemplate.SEND_TEMPLATE_05;
			break;
        case "6":
            wst = WechatSendTemplate.SEND_TEMPLATE_06;
            break;
        case "7":
			wst = WechatSendTemplate.SEND_TEMPLATE_07;
			break;
        case "8":
        	wst = WechatSendTemplate.SEND_TEMPLATE_08;
        	break;
        }

        message.setTemplateId(wst.getTemplateId());
		
		AccessToken accessToken = WxConsts.getAccessToken();
		
		String sendUrl = WxConsts.getWeChatApiURL(WxConsts.POST_SEND_TEMPLATE,accessToken.getAccessToken());
		
		/**
		 *  {"errcode":0,"errmsg":"ok","msgid":200228332}
		 */
		JSONObject jobj = httpRequest(sendUrl, WxConsts.HTTP_POST, message.toString());
		if(null != jobj &&  "0".equals(jobj.get("errcode").toString())){
			map.put("err_code", 200);
			map.put("err_msg", "发送消息模板成功");
			map.put("msg_id", jobj.get("msgid"));
		}else{
			map.put("err_code", 4002);
			map.put("err_msg", "发送消息模板不成功");
		}
		return map;
	}
	
	
	/**
	 * 发送成为会员的模板 
	 * {{first.DATA}}
	 * 会员号：{{cardNumber.DATA}}
	 * {{type.DATA}}地址：{{address.DATA}}
	 * 登记姓名：{{VIPName.DATA}}
	 * 登记手机号：{{VIPPhone.DATA}}
	 * 有效期：{{expDate.DATA}}
	 * {{remark.DATA}}
	 * 
	 * @param cardNumber  会员号
	 * @param VIPName 登记姓名
	 * @param VIPPhone 登记手机号
	 * @param expDate 有效期
	 * @param url 跳转链接
	 * @param openId openId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Object sendWechatTemplateMessageVip( String cardNumber
			, String VIPName , String VIPPhone, String expDate 
			,String url ,String openId){
		Map<String,Object> map = new HashMap<String,Object>();
		TemplateMessage message = new TemplateMessage();
		message.setOpenid(openId);
		message.setUrl(url);
		message.setSendType("3");
		
		Map<String,String> dataMap = new HashMap<String,String>();
		dataMap.put("first", "恭喜您，您已成功成为会员！现在可以免费看海量微课了");
		dataMap.put("cardNumber", cardNumber);
		dataMap.put("type", "使用");
		dataMap.put("address", "365家长课堂");
		dataMap.put("VIPName", VIPName);
		dataMap.put("VIPPhone", VIPPhone);
		dataMap.put("expDate", expDate);
		dataMap.put("remark", "");
		
		message.setDataMap(dataMap);
		
		map = (Map<String, Object>) sendWechatTemplateMessage(message);
		return map;
	}
	
	/**
	 * 课程状态变化通知
	 * 您好，{{userName.DATA}}。
		{{courseName.DATA}}即将于{{date.DATA}}开始{{courseState.DATA}}了。
		{{remark.DATA}}
	 * 
	 * @param userName  用户名称
	 * @param courseName 课程包名称
	 * @param date 有效期
	 * @param url 跳转链接
	 * @param openId openId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Object sendWechatTemplateMessageExpireCourcePackageVip( String userName
			, String courseName , String date 
			,String url ,String openId){
		Map<String,Object> map = new HashMap<String,Object>();
		TemplateMessage message = new TemplateMessage();
		message.setOpenid(openId);
		message.setUrl(url);
		message.setSendType("4");
		
		Map<String,String> dataMap = new HashMap<String,String>();
		dataMap.put("userName", userName );
		dataMap.put("courseName", "您购买的课程：" + courseName);
		dataMap.put("date", date);
		dataMap.put("courseState", "到期");
		dataMap.put("remark", "现在续费会员，免费畅游！");
		
		message.setDataMap(dataMap);
		
		map = (Map<String, Object>) sendWechatTemplateMessage(message);
		return map;
	}

    /**
     * 微课上新课通知
     * 您好，{{userName.DATA}}。
     * {{courseName.DATA}}即将于{{date.DATA}}开始{{courseState.DATA}}了。
     * {{remark.DATA}}
     *
     * @param userName   用户名称
     * @param courseName 课程包名称
     * @param date       有效期
     * @param url        跳转链接
     * @param openId     openId
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Object sendWechatTemplateMessageSubscription(String userName
            , String courseName, String date
            , String url, String openId) {
        Map<String, Object> map = new HashMap<String, Object>();
        TemplateMessage message = new TemplateMessage();
        message.setOpenid(openId);
        message.setUrl(url);
        message.setSendType("4");

        Map<String, String> dataMap = new HashMap<String, String>();
        dataMap.put("userName", userName);
        dataMap.put("courseName", courseName);
        dataMap.put("date", date);
        dataMap.put("courseState", "上线");
        dataMap.put("remark", "您订阅的365家长课堂新课有上新哟，欢迎抢看！");

        message.setDataMap(dataMap);

        map = (Map<String, Object>) sendWechatTemplateMessage(message);
        return map;
    }
    
    /**
     * 课程更新提醒
     * @desc 消息模板对应的详细内容 dataMap
	 * {{first.DATA}}                     
	 * 课程名称：{{keyword1.DATA}}
     * 课程类别：{{keyword2.DATA}}
     * 课程老师：{{keyword3.DATA}}
     * 课程时间：{{keyword4.DATA}}
     * {{remark.DATA}}
     *
     * @param userName   用户名称
     * @param courseName 课程包名称
     * @param date       有效期
     * @param url        跳转链接
     * @param openId     openId
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Object sendWechatTemplateMessageCourseRelease(
            String first, String remark,
            String courseName, String courseTypes, String teachers
            , String date, String url, String openId) {
        Map<String, Object> map = new HashMap<String, Object>();
        TemplateMessage message = new TemplateMessage();
        message.setOpenid(openId);
        message.setUrl(url);
        message.setSendType("7");

        Map<String, String> dataMap = new HashMap<String, String>();
        dataMap.put("first", first);
        dataMap.put("keyword1", courseName);
        dataMap.put("keyword2", courseTypes);
        dataMap.put("keyword3", teachers);
        dataMap.put("keyword4", date);
        dataMap.put("remark", remark);

        message.setDataMap(dataMap);

        map = (Map<String, Object>) sendWechatTemplateMessage(message);
        return map;
    }

    /**
     * 课程更新提醒
     *
     * @param userName   用户名称
     * @param courseName 课程包名称
     * @param date       有效期
     * @param url        跳转链接
     * @param openId     openId
     * @return
     * @desc 消息模板对应的详细内容 dataMap
     * {{first.DATA}}
     * 课程名称：{{keyword1.DATA}}
     * 课程类别：{{keyword2.DATA}}
     * 课程老师：{{keyword3.DATA}}
     * 课程时间：{{keyword4.DATA}}
     * {{remark.DATA}}
     */
    @SuppressWarnings("unchecked")
    public static Object sendWechatTemplateMessageCourseRelease2(
            String first, String remark,
            String courseName, String courseTypes, String teachers
            , String date, String url, List<String> list) {
        Map<String, Object> map = new HashMap<String, Object>();
        TemplateMessage message = new TemplateMessage();
        message.setOpenids(list);
        message.setUrl(url);
        message.setSendType("7");

        Map<String, String> dataMap = new HashMap<String, String>();
        dataMap.put("first", first);
        dataMap.put("keyword1", courseName);
        dataMap.put("keyword2", courseTypes);
        dataMap.put("keyword3",teachers );
        dataMap.put("keyword4", date);
        dataMap.put("remark", remark);

        message.setDataMap(dataMap);

        map = (Map<String, Object>) sendWechatTemplateMessage(message);
        return map;
    }

    /**
	 * 会员到期提醒
	 * {{first.DATA}}
		您的{{name.DATA}}有效期至{{expDate.DATA}}。
		{{remark.DATA}}
	 * 
	 * @param expDate 有效期
	 * @param url 跳转链接
	 * @param openId openId
	 * @return 
	 */
	@SuppressWarnings("unchecked")
	public static Object sendWechatTemplateMessageExpireVip( String expDate 
			,String url ,String openId){
		Map<String,Object> map = new HashMap<String,Object>();
		
		TemplateMessage message = new TemplateMessage();
		message.setOpenid(openId);
		message.setUrl(url);
		message.setSendType("1");
		
		Map<String,String> dataMap = new HashMap<String,String>();
		dataMap.put("first", "您好，开通会员海量家庭教育微课免费听" );
		dataMap.put("name", "365家长课堂会员" );
		dataMap.put("expDate", expDate);
		dataMap.put("remark", "现在续费，防止过期失效");
		
		message.setDataMap(dataMap);
		
		map = (Map<String, Object>) sendWechatTemplateMessage(message);
		return map;
	}


	
	/**
	 * 收入到帐提醒
	 * {{first.DATA}}
		收入金额：{{keyword1.DATA}}
		收入类型：{{keyword2.DATA}}
		交易号：{{keyword3.DATA}}
		到帐时间：{{keyword4.DATA}}
		{{remark.DATA}}
	 * @param first 
	 * @param money 收入金额
	 * @param tradeNo 交易号
	 * @param expDate 到账时间
	 * @param url 跳转链接
	 * @param openId openId
	 * @return 
	 */
	@SuppressWarnings("unchecked")
	public static Object sendWechatTemplateMessageIncome( String first 
			,String money ,String tradeNo , String expireDate 
			, String url,String openId){
		Map<String,Object> map = new HashMap<String,Object>();
		
		TemplateMessage message = new TemplateMessage();
		message.setOpenid(openId);
		message.setUrl(url);
		message.setSendType("5");
		
		Map<String,String> dataMap = new HashMap<String,String>();
		dataMap.put("first", "您有一笔365家长课堂推广收入，请笑纳");
		dataMap.put("keyword1", money);//收益金额
		dataMap.put("keyword2", "推广收入");
		dataMap.put("keyword3", tradeNo);
		dataMap.put("keyword4", expireDate);
		
		message.setDataMap(dataMap);
		
		map = (Map<String, Object>) sendWechatTemplateMessage(message);
		return map;
	}
	
	
	/**
	 * 
	 {{first.DATA}}
	活动主题：{{keyword1.DATA}}
	活动时间：{{keyword2.DATA}}
	活动结果：{{keyword3.DATA}}
	{{remark.DATA}}
	 * @param url
	 * @param openId
	 * @return
	 */
	public static Object sendWechatTemplateMessageActivity(String first, String key1, String key2, String key3, String remark,
			String url,String openId){
		
		
		Map<String,Object> map = new HashMap<String,Object>();
		
		TemplateMessage message = new TemplateMessage();
		message.setOpenid(openId);
		message.setUrl(url);
		message.setSendType("8");
		
		Map<String,String> dataMap = new HashMap<String,String>();
		dataMap.put("first", first);
		dataMap.put("keyword1", key1);
		dataMap.put("keyword2", key2);
		dataMap.put("keyword3", key3);
		dataMap.put("remark", remark);
		
		message.setDataMap(dataMap);
		
		
		map = (Map<String, Object>) sendWechatTemplateMessage(message);
		return map;
		
	}
	
}
